
#include "CalendarTrans.h"


TBool MyCalendarTransNode::_GetItem(MyCalendarTransNode& aNode, TInt idx)
	{
	if (!(idx >= 0 && idx < _GetCalendarTransTableLen()))
		return EFalse;
	
	TInt64 k = _GetCalendarTransTable(idx);

	aNode.iDate.iYear = 			((k >> 32) & ((1 << 8) - 1)) + 1900;
	aNode.iDate.iMonth = 			((k >> 28) & ((1 << 4) - 1)) + 1;
	aNode.iDate.iDay = 				((k >> 23) & ((1 << 5) - 1)) + 1;
	aNode.iChineseDate.iCycle = 	((k >> 21) & ((1 << 2) - 1)) + 76;
	aNode.iChineseDate.iYear = 		((k >> 15) & ((1 << 6) - 1)) + 1;
	aNode.iChineseDate.iMonth = 	((k >> 11) & ((1 << 4) - 1)) + 1;
	aNode.iChineseDate.iLeapMonth = ((k >> 10) & ((1 << 1) - 1));
	aNode.iChineseDate.iDay = 		((k >>  5) & ((1 << 5) - 1)) + 1;
	aNode.iCount = 					((k >>  0) & ((1 << 5) - 1));
	return ETrue;
	}
EXPORT_C TInt MyDate::operator -(const MyDate& bDate) const
	{
	if (iYear != bDate.iYear) return iYear - bDate.iYear;
	if (iMonth != bDate.iMonth) return iMonth - bDate.iMonth;
	if (iDay != bDate.iDay) return iDay - bDate.iDay;
	return 0;
	}
EXPORT_C TInt MyChineseDate::operator -(const MyChineseDate& bChineseDate) const
	{
	if (iCycle != bChineseDate.iCycle) return iCycle - bChineseDate.iCycle;
	if (iYear != bChineseDate.iYear) return iYear - bChineseDate.iYear;
	if (iMonth != bChineseDate.iMonth) return iMonth - bChineseDate.iMonth;
	if (iLeapMonth != bChineseDate.iLeapMonth) return iLeapMonth - bChineseDate.iLeapMonth;
	if (iDay != bChineseDate.iDay) return iDay - bChineseDate.iDay;
	return 0;
	}

EXPORT_C TBool MyChineseCalendarConverter::DateTimeToChineseL(MyDate aDateTime, MyChineseDate& aChineseDate)
	{
	MyCalendarTransNode aNode;
	TInt l = 0;
	TInt r = MyCalendarTransNode::_GetCalendarTransTableLen() - 1;
	while (l <= r)
		{
		TInt mid = (l + r) / 2;
		MyCalendarTransNode::_GetItem(aNode, mid);

		TInt cmp_l = aDateTime - aNode.iDate;
		aNode.iDate.iDay += aNode.iCount - 1;
		TInt cmp_u = aDateTime - aNode.iDate;
		aNode.iDate.iDay -= aNode.iCount - 1; // 还原

		if (cmp_l < 0)
			r = mid - 1;
		else if (cmp_u > 0)
			l = mid + 1;
		else
			{
			aChineseDate = aNode.iChineseDate;
			aChineseDate.iDay += aDateTime.iDay - aNode.iDate.iDay;
			return ETrue;
			}
		}
	return EFalse;
	}

EXPORT_C TBool MyChineseCalendarConverter::ChineseToDateTimeL(MyChineseDate aChineseDate, MyDate& aDateTime)
	{
	MyCalendarTransNode aNode;
	TInt l = 0;
	TInt r = MyCalendarTransNode::_GetCalendarTransTableLen() - 1;
	while (l <= r)
		{
		TInt mid = (l + r) / 2;
		MyCalendarTransNode::_GetItem(aNode, mid);
		
		TInt cmp_l = aChineseDate - aNode.iChineseDate;
		aNode.iChineseDate.iDay += aNode.iCount - 1;
		TInt cmp_u = aChineseDate - aNode.iChineseDate;
		aNode.iChineseDate.iDay -= aNode.iCount - 1; // 还原
		
		if (cmp_l < 0)
			r = mid - 1;
		else if (cmp_u > 0)
			l = mid + 1;
		else
			{
			aDateTime = aNode.iDate;
			aDateTime.iDay += aChineseDate.iDay - aNode.iChineseDate.iDay;
			return ETrue;
			}
		}
	return EFalse;
	}

EXPORT_C void MyChineseCalendarConverter::DateRange(MyDate& aLower, MyDate& aUpper)
	{
	MyCalendarTransNode aFirst, aLast;
	MyCalendarTransNode::_GetItem(aFirst, 0);
	MyCalendarTransNode::_GetItem(aLast, MyCalendarTransNode::_GetCalendarTransTableLen() - 1);
	aLower = aFirst.iDate;
	aUpper = aLast.iDate;
	}

EXPORT_C void MyChineseCalendarConverter::DateRange(MyChineseDate& aLower, MyChineseDate& aUpper)
	{
	MyCalendarTransNode aFirst, aLast;
	MyCalendarTransNode::_GetItem(aFirst, 0);
	MyCalendarTransNode::_GetItem(aLast, MyCalendarTransNode::_GetCalendarTransTableLen() - 1);
	aLower = aFirst.iChineseDate;
	aUpper = aLast.iChineseDate;
	}
